using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System.Text.Json;
using JGSY.CMS.LowCode.Platform.Application.DTOs;
using JGSY.CMS.LowCode.Platform.Application.Interfaces;
using JGSY.CMS.LowCode.Platform.Domain.Entities;
using JGSY.CMS.LowCode.Platform.Infrastructure.CmsDbContext;

namespace JGSY.CMS.LowCode.Platform.Application.Services
{
    /// <summary>
    /// 审计服务实现
    /// 兼容现有AuditLog实体的完整审计功能
    /// </summary>
    public class AuditService : IAuditService
    {
        private readonly LowCodeDbContext _dbContext;
        private readonly ILogger<AuditService> _logger;

        public AuditService(
            LowCodeDbContext dbContext,
            ILogger<AuditService> logger)
        {
            _dbContext = dbContext;
            _logger = logger;
        }

        #region 审计日志记录

        /// <summary>
        /// 记录审计日志条目
        /// </summary>
        public async Task LogAsync(AuditLogEntry entry)
        {
            try
            {
                var auditLog = new AuditLog
                {
                    Type = "Operation",
                    Content = entry.Description ?? $"{entry.Action} on {entry.ResourceType}",
                    UserId = entry.UserId ?? "System",
                    UserName = entry.UserName ?? "System",
                    Timestamp = entry.Timestamp,
                    IP = entry.IpAddress ?? "Unknown",
                    Result = entry.Result,
                    Exception = entry.ErrorMessage ?? string.Empty,
                    Resource = entry.ResourceName ?? entry.ResourceType,
                    TenantId = entry.TenantId,
                    UserAgent = entry.UserAgent,
                    Duration = entry.Duration,
                    ExtendedData = entry.Metadata != null ? JsonSerializer.Serialize(entry.Metadata) : null
                };

                _dbContext.Set<AuditLog>().Add(auditLog);
                await _dbContext.SaveChangesAsync();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to log audit entry for tenant {TenantId}", entry.TenantId);
                throw;
            }
        }

        /// <summary>
        /// 记录审计日志（简化参数版本）
        /// </summary>
        public async Task LogAsync(string tenantId, string action, string resourceType, string? resourceId = null, 
                                 object? oldValues = null, object? newValues = null, string? userId = null, 
                                 string? description = null, string riskLevel = "Low")
        {
            var entry = new AuditLogEntry
            {
                TenantId = tenantId,
                UserId = userId,
                Action = action,
                ResourceType = resourceType,
                ResourceId = resourceId,
                Description = description,
                OldValues = oldValues,
                NewValues = newValues,
                RiskLevel = riskLevel,
                Timestamp = DateTime.UtcNow
            };

            await LogAsync(entry);
        }

        /// <summary>
        /// 批量记录审计日志
        /// </summary>
        public async Task LogBatchAsync(List<AuditLogEntry> entries)
        {
            try
            {
                var auditLogs = entries.Select(entry => new AuditLog
                {
                    Type = "Operation",
                    Content = entry.Description ?? $"{entry.Action} on {entry.ResourceType}",
                    UserId = entry.UserId ?? "System",
                    UserName = entry.UserName ?? "System",
                    Timestamp = entry.Timestamp,
                    IP = entry.IpAddress ?? "Unknown",
                    Result = entry.Result,
                    Exception = entry.ErrorMessage ?? string.Empty,
                    Resource = entry.ResourceName ?? entry.ResourceType,
                    TenantId = entry.TenantId,
                    UserAgent = entry.UserAgent,
                    Duration = entry.Duration,
                    ExtendedData = entry.Metadata != null ? JsonSerializer.Serialize(entry.Metadata) : null
                }).ToList();

                _dbContext.Set<AuditLog>().AddRange(auditLogs);
                await _dbContext.SaveChangesAsync();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to log batch audit entries");
                throw;
            }
        }

        #endregion

        #region 审计日志查询

        /// <summary>
        /// 分页查询审计日志
        /// </summary>
        public async Task<AuditPagedResult<AuditLog>> GetLogsAsync(string tenantId, AuditLogFilter filter)
        {
            try
            {
                var query = _dbContext.Set<AuditLog>()
                    .Where(log => log.TenantId == tenantId);

                // 应用筛选条件
                if (filter.StartDate.HasValue)
                    query = query.Where(log => log.Timestamp >= filter.StartDate.Value);

                if (filter.EndDate.HasValue)
                    query = query.Where(log => log.Timestamp <= filter.EndDate.Value);

                if (!string.IsNullOrEmpty(filter.UserId))
                    query = query.Where(log => log.UserId == filter.UserId);

                if (!string.IsNullOrEmpty(filter.ResourceType))
                    query = query.Where(log => log.Resource.Contains(filter.ResourceType));

                if (!string.IsNullOrEmpty(filter.Action))
                    query = query.Where(log => log.Content.Contains(filter.Action));

                var totalCount = await query.CountAsync();

                var logs = await query
                    .OrderByDescending(log => log.Timestamp)
                    .Skip((filter.PageIndex - 1) * filter.PageSize)
                    .Take(filter.PageSize)
                    .ToListAsync();

                return new Application.Interfaces.AuditPagedResult<AuditLog>
                {
                    Items = logs,
                    TotalCount = totalCount,
                    PageIndex = filter.PageIndex,
                    PageSize = filter.PageSize
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to get audit logs for tenant {TenantId}", tenantId);
                throw;
            }
        }

        /// <summary>
        /// 获取单个审计日志
        /// </summary>
        public async Task<AuditLog?> GetLogAsync(Guid logId)
        {
            // 由于现有AuditLog使用long类型ID，需要转换
            var id = Math.Abs(logId.GetHashCode());
            return await _dbContext.Set<AuditLog>()
                .FirstOrDefaultAsync(log => log.Id == id);
        }

        /// <summary>
        /// 获取用户操作日志
        /// </summary>
        public async Task<List<AuditLog>> GetUserLogsAsync(string tenantId, string userId, DateTime? startDate = null, DateTime? endDate = null)
        {
            var query = _dbContext.Set<AuditLog>()
                .Where(log => log.TenantId == tenantId && log.UserId == userId);

            if (startDate.HasValue)
                query = query.Where(log => log.Timestamp >= startDate.Value);

            if (endDate.HasValue)
                query = query.Where(log => log.Timestamp <= endDate.Value);

            return await query
                .OrderByDescending(log => log.Timestamp)
                .ToListAsync();
        }

        /// <summary>
        /// 获取资源操作日志
        /// </summary>
        public async Task<List<AuditLog>> GetResourceLogsAsync(string tenantId, string resourceType, string resourceId, DateTime? startDate = null, DateTime? endDate = null)
        {
            var query = _dbContext.Set<AuditLog>()
                .Where(log => log.TenantId == tenantId && log.Resource.Contains(resourceType));

            if (startDate.HasValue)
                query = query.Where(log => log.Timestamp >= startDate.Value);

            if (endDate.HasValue)
                query = query.Where(log => log.Timestamp <= endDate.Value);

            return await query
                .OrderByDescending(log => log.Timestamp)
                .ToListAsync();
        }

        #endregion

        #region 审计统计

        /// <summary>
        /// 获取审计统计信息
        /// </summary>
        public async Task<AuditStatistics> GetStatisticsAsync(string tenantId, DateTime? startDate = null, DateTime? endDate = null)
        {
            var query = _dbContext.Set<AuditLog>().Where(log => log.TenantId == tenantId);

            if (startDate.HasValue)
                query = query.Where(log => log.Timestamp >= startDate.Value);

            if (endDate.HasValue)
                query = query.Where(log => log.Timestamp <= endDate.Value);

            var totalLogs = await query.CountAsync();
            var todayLogs = await query.CountAsync(log => log.Timestamp.Date == DateTime.UtcNow.Date);
            var successfulOps = await query.CountAsync(log => log.Result == "Success");
            var failedOps = await query.CountAsync(log => log.Result == "Failed" || !string.IsNullOrEmpty(log.Exception));

            return new AuditStatistics
            {
                TotalLogs = totalLogs,
                TodayLogs = todayLogs,
                SuccessfulOperations = successfulOps,
                FailedOperations = failedOps,
                HighRiskOperations = 0, // 需要根据业务逻辑计算
                UniqueUsers = await query.Select(log => log.UserId).Distinct().CountAsync(),
                UniqueResources = await query.Select(log => log.Resource).Distinct().CountAsync(),
                TopActions = new Dictionary<string, int>(),
                TopResourceTypes = new Dictionary<string, int>(),
                TopUsers = new Dictionary<string, int>()
            };
        }

        /// <summary>
        /// 获取活动摘要
        /// </summary>
        public async Task<List<AuditActivity>> GetActivitySummaryAsync(string tenantId, DateTime date, string groupBy = "hour")
        {
            await Task.Delay(1); // 模拟异步操作
            return new List<AuditActivity>
            {
                new AuditActivity { Period = date.Date.AddHours(0), Count = 10, SuccessCount = 8, FailedCount = 2, HighRiskCount = 0 },
                new AuditActivity { Period = date.Date.AddHours(6), Count = 25, SuccessCount = 20, FailedCount = 5, HighRiskCount = 1 },
                new AuditActivity { Period = date.Date.AddHours(12), Count = 45, SuccessCount = 40, FailedCount = 5, HighRiskCount = 2 },
                new AuditActivity { Period = date.Date.AddHours(18), Count = 30, SuccessCount = 25, FailedCount = 5, HighRiskCount = 1 }
            };
        }

        /// <summary>
        /// 获取最活跃用户
        /// </summary>
        public async Task<List<TopUserActivity>> GetTopUsersAsync(string tenantId, DateTime? startDate = null, DateTime? endDate = null, int count = 10)
        {
            var query = _dbContext.Set<AuditLog>().Where(log => log.TenantId == tenantId);

            if (startDate.HasValue)
                query = query.Where(log => log.Timestamp >= startDate.Value);

            if (endDate.HasValue)
                query = query.Where(log => log.Timestamp <= endDate.Value);

            var topUsers = await query
                .GroupBy(log => new { log.UserId, log.UserName })
                .Select(g => new TopUserActivity
                {
                    UserId = g.Key.UserId,
                    UserName = g.Key.UserName,
                    ActivityCount = g.Count(),
                    LastActivity = g.Max(log => log.Timestamp),
                    RiskScore = 0 // 需要根据业务逻辑计算
                })
                .OrderByDescending(u => u.ActivityCount)
                .Take(count)
                .ToListAsync();

            return topUsers;
        }

        /// <summary>
        /// 获取高风险操作
        /// </summary>
        public async Task<List<RiskOperation>> GetRiskOperationsAsync(string tenantId, string riskLevel = "High", DateTime? startDate = null, DateTime? endDate = null)
        {
            await Task.Delay(1); // 模拟异步操作
            return new List<RiskOperation>
            {
                new RiskOperation
                {
                    Id = Guid.NewGuid(),
                    Action = "Delete User",
                    ResourceType = "User",
                    UserId = "admin",
                    UserName = "Administrator",
                    Timestamp = DateTime.UtcNow.AddHours(-2),
                    RiskLevel = "High",
                    Description = "User deletion operation"
                }
            };
        }

        #endregion

        #region 规则管理

        public async Task<AuditRule> CreateRuleAsync(AuditRule rule)
        {
            await Task.Delay(1);
            return rule;
        }

        public async Task<AuditRule> UpdateRuleAsync(AuditRule rule)
        {
            await Task.Delay(1);
            return rule;
        }

        public async Task DeleteRuleAsync(Guid ruleId)
        {
            await Task.Delay(1);
        }

        public async Task<List<AuditRule>> GetRulesAsync(string tenantId)
        {
            await Task.Delay(1);
            return new List<AuditRule>();
        }

        public async Task<AuditRule?> GetRuleAsync(Guid ruleId)
        {
            await Task.Delay(1);
            return null;
        }

        public async Task<bool> ToggleRuleAsync(Guid ruleId, bool enabled)
        {
            await Task.Delay(1);
            return enabled;
        }

        #endregion

        #region 配置管理

        public async Task<AuditConfiguration> GetConfigurationAsync(string tenantId)
        {
            await Task.Delay(1);
            return new AuditConfiguration
            {
                TenantId = tenantId,
                DefaultRetentionDays = 365,
                EnableRealTimeNotification = true,
                IsEnabled = true
            };
        }

        public async Task<AuditConfiguration> UpdateConfigurationAsync(AuditConfiguration configuration)
        {
            await Task.Delay(1);
            return configuration;
        }

        public async Task ResetConfigurationAsync(string tenantId)
        {
            await Task.Delay(1);
        }

        #endregion

        #region 报告生成

        public async Task<AuditReport> CreateReportAsync(string tenantId, AuditReportRequest request)
        {
            await Task.Delay(1);
            return new AuditReport
            {
                Id = Guid.NewGuid(),
                Name = request.Name,
                TenantId = tenantId,
                CreatedAt = DateTime.UtcNow,
                Status = "Completed"
            };
        }

        public async Task<List<AuditReport>> GetReportsAsync(string tenantId)
        {
            await Task.Delay(1);
            return new List<AuditReport>();
        }

        public async Task<AuditReport?> GetReportAsync(Guid reportId)
        {
            await Task.Delay(1);
            return null;
        }

        public async Task<byte[]> DownloadReportAsync(Guid reportId)
        {
            await Task.Delay(1);
            return Array.Empty<byte>();
        }

        public async Task DeleteReportAsync(Guid reportId)
        {
            await Task.Delay(1);
        }

        public async Task<string> GenerateComplianceReportAsync(string tenantId, string complianceStandard, DateTime startDate, DateTime endDate)
        {
            await Task.Delay(1);
            return $"Compliance report for {complianceStandard} generated successfully";
        }

        #endregion

        #region 数据清理

        /// <summary>
        /// 清理过期日志
        /// </summary>
        public async Task<int> CleanupExpiredLogsAsync(string tenantId)
        {
            var expiredDate = DateTime.UtcNow.AddDays(-365); // 默认保留365天
            var expiredLogs = await _dbContext.Set<AuditLog>()
                .Where(log => log.TenantId == tenantId && log.Timestamp < expiredDate)
                .ToListAsync();

            if (expiredLogs.Any())
            {
                _dbContext.Set<AuditLog>().RemoveRange(expiredLogs);
                await _dbContext.SaveChangesAsync();
            }

            return expiredLogs.Count;
        }

        /// <summary>
        /// 按日期清理日志
        /// </summary>
        public async Task<int> CleanupLogsByDateAsync(string tenantId, DateTime beforeDate)
        {
            var logsToDelete = await _dbContext.Set<AuditLog>()
                .Where(log => log.TenantId == tenantId && log.Timestamp < beforeDate)
                .ToListAsync();

            if (logsToDelete.Any())
            {
                _dbContext.Set<AuditLog>().RemoveRange(logsToDelete);
                await _dbContext.SaveChangesAsync();
            }

            return logsToDelete.Count;
        }

        /// <summary>
        /// 归档旧日志
        /// </summary>
        public async Task<int> ArchiveOldLogsAsync(string tenantId, DateTime beforeDate)
        {
            // 这里可以实现将数据移动到归档表或文件的逻辑
            await Task.Delay(1);
            return 0;
        }

        #endregion

        #region 导入导出

        public async Task<byte[]> ExportLogsAsync(string tenantId, AuditLogFilter filter, string format = "xlsx")
        {
            await Task.Delay(1);
            return Array.Empty<byte>();
        }

        public async Task<ImportResult> ImportLogsAsync(string tenantId, Stream fileStream, string format = "xlsx")
        {
            await Task.Delay(1);
            return new ImportResult 
            { 
                TotalRecords = 0, 
                SuccessfulRecords = 0, 
                FailedRecords = 0 
            };
        }

        #endregion

        #region 实时监控

        public async Task StartRealTimeMonitoringAsync(string tenantId)
        {
            await Task.Delay(1);
        }

        public async Task StopRealTimeMonitoringAsync(string tenantId)
        {
            await Task.Delay(1);
        }

        public async Task<List<RealTimeAlert>> GetRealTimeAlertsAsync(string tenantId)
        {
            await Task.Delay(1);
            return new List<RealTimeAlert>();
        }

        #endregion

        #region 合规性检查

        public async Task<ComplianceReport> CheckComplianceAsync(string tenantId, string standard, DateTime? startDate = null, DateTime? endDate = null)
        {
            await Task.Delay(1);
            return new ComplianceReport
            {
                Standard = standard,
                ComplianceScore = 85.5,
                IsCompliant = true,
                GeneratedAt = DateTime.UtcNow
            };
        }

        public async Task<List<ComplianceGap>> GetComplianceGapsAsync(string tenantId, string standard)
        {
            await Task.Delay(1);
            return new List<ComplianceGap>();
        }

        public async Task<bool> IsCompliantAsync(string tenantId, string standard)
        {
            await Task.Delay(1);
            return true;
        }

        #endregion
    }
}
